package week1;

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;

/**
 * Created by dyc on 2016/10/14.
 */
public class PercolationStats {
    private int n;
    private double mean;
    private double stddev;
    private double confidenceLo;
    private double confidenceHi;
    private Percolation percolation;
    public PercolationStats(int n,int trials){
        if (n <= 0 || trials <= 0)
            throw new IllegalArgumentException();
        this.n = n;
        double[] expResult = new double[trials];
        for (int i = 0; i < trials; i++){
            expResult[i] = experiment();
            expResult[i] /= n * n;
        }

        mean = StdStats.mean(expResult);
        stddev = StdStats.stddev(expResult);
        confidenceLo = mean - 1.96 * stddev / Math.sqrt(trials);
        confidenceHi = mean + 1.96 * stddev / Math.sqrt(trials);
    }

    private int experiment(){
        int[] sites = new int[n * n];
        for (int i = 0; i < sites.length; i++){
            sites[i] = i + 1;
        }
        percolation = new Percolation(n);
        int openCount = 0;
        while (!percolation.percolates()){
            int index = StdRandom.uniform(sites.length - openCount);
            int[] coordination = index2Coordination(sites[index]);
            percolation.open(coordination[0],coordination[1]);
            int endIndex = sites.length - openCount - 1;
            int tmp = sites[endIndex];
            sites[endIndex] = sites[index];
            sites[index] = tmp;
            openCount++;
        }
        return openCount;
    }

    private int[] index2Coordination(int index){
        int[] coordination = new int[2];
        coordination[0] = 1 + (index - 1) / n;
        coordination[1] = index - (coordination[0] - 1) * n;
        return coordination;
    }

    public double mean(){
        return mean;
    }

    public double stddev(){
        return stddev;
    }

    public double confidenceLo(){
        return confidenceLo;
    }

    public double confidenceHi(){
        return confidenceHi;
    }

    public static void main(String[] args){
        PercolationStats stats = new PercolationStats(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
        StdOut.println("mean                    = " + stats.mean());
        StdOut.println("stddev                  = " + stats.stddev());
        StdOut.println("95% confidence interval = " + stats.confidenceLo() + ", " + stats.confidenceHi());

    }
}
